/**
 * 根据页面和图中添加的图形.创建一个所有图形之间的树形关系的侧边浏览窗口
 */
function SidebarStructure(editorUi, container) {
  this.editorUi = editorUi;
  this.sidebar = editorUi.sidebar
  this.container = container;
  this.graph = editorUi.createTemporaryGraph(this.editorUi.editor.graph.getStylesheet());
  this.graph.cellRenderer.minSvgStrokeWidth = 1;
  this.graph.cellRenderer.antiAlias = false;
  this.graph.container.style.visibility = 'hidden';
  this.graph.foldingEnabled = false;

  this.nodeList = [] // zTree的平面数据
  this.treeData = [] // zTree的树形数据

  this.editNode = null

  this.selectedNodeId = null // 已选中的节点id
  this.expandNodeList = [] // 已展开的节点

  this.zTreeObj = null

  this.visible = true;
  this.createStructureTree(); //创建树结构
}

SidebarStructure.prototype.show = function () {
  if (!this.visible) {
    this.container.style.display = 'block';
    this.visible = true;
  }
}

SidebarStructure.prototype.hide = function () {
  if (this.visible) {
    this.container.style.display = 'none';
    this.visible = false;
  }
}

SidebarStructure.prototype.createNode = function (cells, title, showLabel, showTitle, width, height, allowCellsInserted, treeNode) {
  var elt = document.createElement('a');
  elt.className = 'geItem';
  elt.style.display = 'inline-flex';
  elt.style.alignItems = 'center';
  elt.style.overflow = 'hidden';
  var border = 2 * this.thumbBorder;
  elt.style.width = '100%'
  elt.style.height = (this.thumbHeight + border) + 'px';
  elt.style.padding = this.thumbPadding + 'px';
  // Blocks default click action


  mxEvent.addListener(elt, 'click', mxUtils.bind(this, function (evt) {
    this.zTreeObj.selectNode(treeNode);
    drawioBus.$emit('modelChange', treeNode)
    this.selectedNodeId = treeNode.id
    mxEvent.consume(evt);
  }));

  this.createItemTitle(cells, this.thumbWidth, this.thumbHeight, elt, title);

  var bounds = new mxRectangle(0, 0, width, height);

  if ((cells.length > 1 || cells[0].vertex)) { // 节点引用只能拖拽创建
    var ds = this.createDragSource(elt, this.createDropHandler(cells, true, allowCellsInserted,
      bounds), this.createDragPreview(width, height), cells, bounds);
    // this.addClickHandler(elt, ds, cells);

    // Uses guides for vertices only if enabled in graph
    ds.isGuidesEnabled = mxUtils.bind(this, function () {
      return this.editorUi.editor.graph.graphHandler.guidesEnabled;
    });
  } else if (cells[0] != null && cells[0].edge) {
    var ds = this.createDragSource(elt, this.createDropHandler(cells, false, allowCellsInserted, bounds), this.createDragPreview(width, height), cells, bounds);
    // this.addClickHandler(elt, ds, cells);
  }

  // Shows a tooltip with the rendered cell
  if (!mxClient.IS_IOS) {
    mxEvent.addGestureListeners(elt, null, mxUtils.bind(this, function (evt) {
      if (mxEvent.isMouseEvent(evt)) {
        this.showTooltip(elt, cells, bounds.width, bounds.height, title, showLabel);
      }
    }));
  }
  return elt;
}

SidebarStructure.prototype.createSequence = function (style, width, height, value, title, showLabel, showTitle, tags, treeNode, modelType, objType, allowCellsInserted) {
  var cells = [new mxCell((value != null) ? value : '', new mxGeometry(0, 0, width, height), style, objType)];
  cells[0].vertex = true;
  cells[0].setConnectable(false)
  cells[0].value = title
  cells[0].treeNodeId = treeNode.id

  cells[0].moduleType = modelType

  tags = (tags != null && tags.length > 0) ? tags : ((title != null) ? title.toLowerCase() : '');
  return this.addEntry(tags, mxUtils.bind(this, function () {
    return SidebarStructure.prototype.createNode.call(this, cells, title, showLabel, showTitle, width, height, allowCellsInserted, treeNode);
  }));
}


SidebarStructure.prototype.createTypeList = async function (treeNode, rightClickContainer) {

  const typeList = await getType(treeNode.type)
  typeList.forEach(item => {
    const li = document.createElement('div')
    li.innerText = '新增' + item.name
    li.style.padding = '0 20px'
    li.style.height = '30px'
    li.style.lineHeight = '30px'
    li.style.fontSize = '14px'
    li.style.color = '#666'
    li.style.cursor = 'pointer'

    li.addEventListener('click', mxUtils.bind(this, function () {
      drawioBus.$emit('openAddStructureDialog', {
        name: item.name,
        metaId: item.id,
        parentId: treeNode.id,
        typeList: typeList,
        callback: () => {
          document.body.removeChild(document.querySelector('#createRightClickDiv'))
        }
      })
    }))
    rightClickContainer.append(li)
  })
  return typeList
}

SidebarStructure.prototype.createRightClickDiv = async function (event, treeId, treeNode) {
  if (document.querySelector('#createRightClickDiv')) {
    document.body.removeChild(document.querySelector('#createRightClickDiv'))
  }

  const rightClickContainer = document.createElement('div')
  rightClickContainer.id = 'createRightClickDiv'
  rightClickContainer.style.position = 'fixed'
  rightClickContainer.style.top = event.clientY + 10 + 'px'
  rightClickContainer.style.left = event.clientX + 10 + 'px'
  rightClickContainer.style.minWidth = '150px'
  rightClickContainer.style.backgroundColor = '#fff'
  rightClickContainer.style.border = '1px solid #eee'
  rightClickContainer.style.borderRadius = '5px'
  rightClickContainer.style.padding = '5px 0'
  rightClickContainer.style.zIndex = '99'

  const closeBtn = document.createElement('div')
  closeBtn.style.position = 'absolute'
  closeBtn.style.top = '0px'
  closeBtn.style.right = '10px'
  closeBtn.style.fontSize = '30px'
  closeBtn.style.color = '#7a7878'
  closeBtn.style.transform = 'rotate(45deg)'
  closeBtn.innerText = '+'
  closeBtn.style.cursor = 'pointer'

  closeBtn.addEventListener('click', function () {
    document.body.removeChild(document.querySelector('#createRightClickDiv'))
  })

  let typeList = []
  if (treeNode instanceof Object && treeNode.canAddModel) {
    typeList = await this.createTypeList(treeNode, rightClickContainer)
  }

  const edit = document.createElement('div')
  edit.innerText = '编辑'
  edit.style.padding = '0 20px'
  edit.style.height = '30px'
  edit.style.lineHeight = '30px'
  edit.style.fontSize = '14px'
  edit.style.color = '#666'
  edit.style.cursor = 'pointer'

  edit.addEventListener('click', mxUtils.bind(this, function () {
    this.editNode = treeNode
    drawioBus.$emit('openAddStructureDialog', {
      name: treeNode.name,
      metaId: treeNode.relateId,
      id: treeNode.id,
      typeList: typeList,
      callback: () => {
        document.body.removeChild(document.querySelector('#createRightClickDiv'))
        this.updateTreeNode()
      }
    })
  }))

  const del = document.createElement('div')
  del.innerText = '删除'
  del.style.padding = '0 20px'
  del.style.height = '30px'
  del.style.lineHeight = '30px'
  del.style.fontSize = '14px'
  del.style.color = '#666'
  del.style.cursor = 'pointer'

  del.addEventListener('click', mxUtils.bind(this, function () {
    drawioBus.$emit('delStructureNode', {
      hasChildren: treeNode.children && treeNode.children.length,
      fn: mxUtils.bind(this, function () {
        window.$axios.post(window.parent.top.g.ApiUrl2 + '/sysmlDefineNode/deleteDefineNodeById?id=' + treeNode.id).then((res) => {
          document.body.removeChild(document.querySelector('#createRightClickDiv'))
          this.updateTreeNode()
        })
      })
    })
  }))
  rightClickContainer.append(edit)
  if (treeNode.type !== 'root') {
    rightClickContainer.append(del)
  }

  rightClickContainer.append(closeBtn)
  document.body.append(rightClickContainer)
}

SidebarStructure.prototype.getTreeData = function (selectId) {
  const taht = this
  const setting = {
    view: {
      selectedMulti: false,
      showIcon: true,
      // 自定义树节点
      addDiyDom: mxUtils.bind(this, function (treeid, treeNode) {
        return
        let aNode = $('#' + treeNode.tId + '_a')

        if (!aNode.length) {
          aNode = window.top.document.getElementById(treeNode.tId + '_a')
          aNode = aNode ? [aNode] : []
        }

        if (!aNode.length) return

        this.sidebar = this.sidebar.graph ? this.sidebar : window.myEditor.sidebar

        // 时序图,时序图可以互相拖拽
        if (treeNode.modelType === 'DIAGRAM_SYSML_SEQUENCE') {
          let fn = this.createSequence.call(this.sidebar, 'rounded=0;whiteSpace=wrap;html=1;', 60, 30, '', treeNode.name, null, null, treeNode.name, treeNode, treeNode.modelType)

          const elt = fn()

          elt.children[0].style.marginLeft = ''

          elt.style.height = '30px'

          aNode[0].querySelector('.node_name').innerText = ''

          aNode[0].append(elt)

          return
        }

        if (treeNode.type === 'relation_package') {
          // || treeNode.type === 'relation_object'
          aNode[0].querySelector('.node_name').innerText = ''

          const div = document.createElement('div')

          div.style.display = 'inline-block'

          const img = document.createElement('img')
          img.src = 'img/sysml/箭头.png'
          img.style.height = '16px'

          div.append(img)

          div.append(`${treeNode.name}`)



          aNode[0].append(div)
          return
        }

        // 元素节点
        if (treeNode.xmlNodeString) {

          window.saveCell = false
          // 不展示svg图标
          //   window.showThumb = false
          // 添加属性selectQuote cellId 标记为直接引用，不用弹出
          const slpitXml = treeNode.xmlNodeString.split('quoteId=')
          if (slpitXml.length === 2) {
            treeNode.xmlNodeString = slpitXml[0] + `selectQuote="false" cellId="${treeNode.relateId}" quoteId=` + slpitXml[1]
          }

          // 根据xml，得到可拖拽的a标签
          const fns = this.sidebar.createFns(`<?xml version="1.0" encoding="UTF-8"?><root>${treeNode.xmlNodeString}</root>`)
          const elt = fns[0]()

          elt.children[0].style.marginLeft = ''

          elt.style.marginLeft = '-5px'

          elt.style.height = '30px'

          aNode[0].querySelector('.node_name').innerText = ''

          aNode[0].append(elt)
        } else {
          aNode[0].querySelector('.node_name').style.marginLeft = '4px'
        }
      }),
    },
    callback: {

      onClick: mxUtils.bind(this, function (event, treeId, treeNode, clickFlag) {
        this.selectedNodeId = treeNode.id
        if (treeNode.type === "model_diagram") {
          drawioBus.$emit('modelChange', treeNode)
        }
      }),
      onExpand: function (event, treeId, treeNode) {
        taht.expandNodeList.push(treeNode)
      },
      onCollapse: function (event, treeId, treeNode) {
        let index = taht.expandNodeList.findIndex(node => node.id === treeNode.id)
        taht.expandNodeList.splice(index, 1)
      },
      onRightClick: function (event, treeId, treeNode) {
        console.log(treeNode);
        taht.createRightClickDiv(event, treeId, treeNode)
      }
    }
  }

  // 获取树形列表
  window.$axios.post(window.parent.top.g.ApiUrl2 + `/sysmlDefineNode/findAllDefineNodeList?taskId=${window.top.getProjectStore(window.top.$constants.TASK_ID)}`, {}).then((res) => {
    this.nodeList = (res.data || [])

    // 递归生成树
    const transTree = (data) => {
      let result = []
      let map = {}
      data.forEach(item => {
        map[item.id] = item
      })
      data.forEach(item => {
        if (item.type === 'root') {
          item.iconSkin = 'iconSkin1'
        } else if (item.type === 'model_diagram') {
          item.iconSkin = 'iconSkin2'
        } else if (item.type === 'model_object') {
          item.iconSkin = 'iconSkin0'
        } else if (item.type === 'model_package') {
          item.iconSkin = 'iconSkin0'
        }

        let parent = map[item.parentId]
        if (parent) {
          item.parentNodeName = parent.name;
          (parent.children || (parent.children = [])).push(item)
        } else {
          item.parentNodeName = ''
          result.push(item)
        }
      })
      return result
    }

    this.treeData = transTree(res.data || [])

    // document.querySelector('#structuretree').innerHTML = ''

    this.zTreeObj = $.fn.zTree.init($(this.container.children[0]), setting, this.treeData);

    setTimeout(() => {
      const nodes = this.zTreeObj.getNodes()
      // 默认展开第一个model_diagram项
      if (this.expandNodeList.length === 0) {
        this.zTreeObj.expandNode(nodes.find(i => i.type === 'root'));

        this.expandNodeList.push(nodes.find(i => i.type === 'root'))
        const row = nodes.find(i => i.type === 'root').children.find(item => item.type === 'model_diagram');
        if (row) {
          this.zTreeObj.selectNode(row);
          drawioBus.$emit('modelChange', row)
        }
      } else {
        function expandSelect(nodes) {
          nodes.forEach(node => {
            if (selectId && selectId === node.id) {
              this.selectedNodeId = selectId
              drawioBus.$emit('modelChange', node)
            }
            if (this.selectedNodeId && this.selectedNodeId === node.id) {
              this.zTreeObj.selectNode(node);
            }
            if (this.expandNodeList.some(item => item.id === node.id)) {
              this.zTreeObj.expandNode(node);
            }
            if (Array.isArray(node.children) && node.children.length) {
              expandSelect.call(this, node.children)
            }
          })
        }
        // 展开 已展开的节点
        expandSelect.call(this, nodes)
      }
    }, 50)
  })
}

SidebarStructure.prototype.createStructureTree = function () {
  const div = document.createElement('div')
  div.id = 'structuretree'
  div.className = 'ztree'
  div.style.width = 'calc(100% - 12px)'
  div.style.height = 'calc(100% - 10px)'
  div.style.overflow = 'scroll'
  div.style.borderRight = '1px solid #eee'

  this.container.appendChild(div);

  this.getTreeData()

  drawioBus.$on('addStructureSuccess', (params) => {
    if (params.id) {
      this.getTreeData(String(params.id))
    } else {
      this.editNode && (this.editNode.name = params.name)
    }
  })
}

// 获取类型 
async function getType(type) {
  let typeList = []
  await window.$axios.post(window.parent.top.g.ApiUrl2 + '/sysmlDefineNode/getSYSMLModelTypes?type=' + type).then((res) => {
    typeList = (res.data || [])
  })
  return typeList

}

// 更新节点
SidebarStructure.prototype.updateTreeNode = function () {
  if (this.zTreeObj) {
    let nodes = this.zTreeObj.currentSelectedNode

    this.selectedNodeId = nodes.id

    this.getTreeData()
  }
}
